#ifndef STUN_PROTOCOL_MSG_H_
#define STUN_PROTOCOL_MSG_H_

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

class StunAttr;
class StunMsg
{
public:
    static constexpr int TRANSACTION_LENGTH = 12;

public:
    StunMsg();
    ~StunMsg();
    void                                     MsgType(int type);
    void                                     MsgLength(int length);
    void                                     MsgMagicCookie(uint32_t magic_cookie);
    void                                     TransactionId(const std::string & transaction);
    void                                     TransactionId(uint8_t * data);
    void                                     AddAttr(const std::shared_ptr<StunAttr>& attr);

    uint16_t                                 MsgType() const;
    uint16_t                                 MsgLength() const;
    uint32_t                                 MsgCookie() const;
    uint8_t *                                TransactionId();
    std::shared_ptr<StunAttr>                AttrByType(uint16_t attr_type);
    std::vector<std::shared_ptr<StunAttr>> & Attr();
    int                                      Compose(uint8_t * data, int data_length);
    void                                     DumpMsgHeader() const;

public:
    static int CreateTransactionID(uint8_t * result);

private:
    uint16_t                               m_msg_type;
    uint16_t                               m_msg_length;
    uint32_t                               m_magic_cookie;
    std::string                            m_hex_transaction_id;
    uint8_t                                m_transaction_id[TRANSACTION_LENGTH];
    std::vector<std::shared_ptr<StunAttr>> m_msg_attr_vec;
};

#endif //! STUN_PROTOCOL_MSG_H_
